package com.kob.backend.consumer;

import com.alibaba.fastjson.JSONObject;
import com.kob.backend.consumer.utils.Game;
import com.kob.backend.consumer.utils.JwtAuthentication;
import com.kob.backend.mapper.BotMapper;
import com.kob.backend.mapper.RecordMapper;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.pojo.Bot;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/websocket/{token}")  // 注意不要以'/'结尾
public class WebSocketServer {

    //用session对象来维护每次的链接
    private Session session = null;
    //链接的客户端
    private User user ;
    //对应客户链接表
    public static ConcurrentHashMap< Integer,WebSocketServer>
            userConnectionInfo = new ConcurrentHashMap<>(); //根据用户的id查找对应的链接
    //线程安全的Set匹配池
    private static CopyOnWriteArraySet<User> matchpool = new CopyOnWriteArraySet<>();
    public Game game  = null;


    //操作数据库
    //@Autowired 静态对象不能直接注入
    public static UserMapper userMapper; //设置静态属性，防止出现多并发
    public static RecordMapper recordMapper ;

    //两个服务之间通信
    public static RestTemplate restTemplate;

    private static BotMapper botMapper;

    private final static String addPlayerUrl = "http://127.0.0.1:3001/player/add/";
    private final static String removePlayerUrl = "http://127.0.0.1:3001/player/remove/";

    @Autowired
    public void setUserMapper(UserMapper userMapper){
        WebSocketServer.userMapper = userMapper;
    }

    @Autowired
    public  void setRecordMapper(RecordMapper recordMapper) {
        WebSocketServer.recordMapper = recordMapper;
        System.out.println("recordMapper 已注入");
    }

    @Autowired
    public  void setRestTemplate(RestTemplate restTemplate) {
        WebSocketServer.restTemplate = restTemplate;
    }

    @Autowired
    public void setBotMapper(BotMapper botMapper) {
        WebSocketServer.botMapper = botMapper;
    }

    public static void  startGame (Integer aId, Integer aBotId,Integer bId , Integer bBotId ){
        User user1 = userMapper.selectById(aId);
        User user2 = userMapper.selectById(bId);
        Bot bot1 = botMapper.selectById(aBotId);
        Bot bot2 = botMapper.selectById(bBotId);
        Game game = new Game(13,14,20, user1.getId(),bot1, user2.getId(),bot2);
        game.createMap(); //创建地图
        //如果有玩家在匹配中强制退出，防止出现异常
        if(userConnectionInfo.get(user1.getId()) != null){
            userConnectionInfo.get(user1.getId()).game = game; //将user1的webserver对象绑定game对象
        }
        if(userConnectionInfo.get(user2.getId()) != null){
            userConnectionInfo.get(user2.getId()).game = game; //将user2的webserver对象绑定game对象
        }


        //启动game
        game.start();
        //将game的相关信息封装成一个JSON
        JSONObject respGame = new JSONObject();
        respGame.put("a_id", game.getPlayerA().getId());
        respGame.put("a_sx", game.getPlayerA().getSx());
        respGame.put("a_sy", game.getPlayerA().getSy());
        respGame.put("b_id", game.getPlayerB().getId());
        respGame.put("b_sx", game.getPlayerB().getSx());
        respGame.put("b_sy", game.getPlayerB().getSy());
        respGame.put("map", game.getG());

        //分别给user1和user2传送消息告诉他们匹配成功了
        //通过user1的连接向user1发消息
        JSONObject resp1 = new JSONObject();
        resp1.put("event","start-matching");
        resp1.put("opponent_username",user2.getUsername());
        resp1.put("opponent_photo",user2.getPhoto());
        resp1.put("game",respGame);
        WebSocketServer webSocketServer1 = userConnectionInfo.get(user1.getId());//获取user1的连接
        if(webSocketServer1 != null){
            webSocketServer1.sendMessage(resp1.toJSONString());
        }


        //通过user2的连接向user2发消息
        JSONObject resp2 = new JSONObject();
        resp2.put("event","start-matching");
        resp2.put("opponent_username",user1.getUsername());
        resp2.put("opponent_photo",user1.getPhoto());
        resp2.put("game",respGame);
        WebSocketServer webSocketServer2 = userConnectionInfo.get(user2.getId());
        if(webSocketServer2 != null){
            webSocketServer2.sendMessage(resp2.toJSONString());
        }
    }
    private void startMatching(Integer botId){
        System.out.println("start matching! ");
        //多值映射
        MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
        data.add("user_id", this.user.getId().toString());
        data.add("rating",this.user.getRating().toString());
        data.add("bot_id",botId.toString());
        //向MatchingSystem发送请求
        restTemplate.postForObject(addPlayerUrl,data,String.class);




    }
    private void stopMatching(){
        System.out.println("stop matching! ");
        //多值映射
        MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
        data.add("user_id", this.user.getId().toString());
        //向MatchingSystem发送请求
        restTemplate.postForObject(removePlayerUrl,data,String.class);

    }

    private void move(Integer direction) {
        //判断是A玩家还是B玩家在操作
        if(game.getPlayerA().getId().equals(user.getId())){
            if(game.getPlayerA().getBotId().equals(-1)){ //防止混淆是人还是Bot进行的操作
                game.setNextStepA(direction);
            }
            System.out.println("nextstepA:"+game.getNextStepA());
        }else if (game.getPlayerB().getId().equals(user.getId())) {
            if(game.getPlayerB().getBotId().equals(-1)){
                game.setNextStepB(direction);
            }
            System.out.println("nextstepB:"+game.getNextStepB());
        } else {
            Exception e = new Exception("Error");
            e.printStackTrace();
        }
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) throws IOException {
        // 建立连接 自动调用
        this.session = session;
        System.out.println("Connected!");

        int userId = JwtAuthentication.getUserId(token);
        this.user = userMapper.selectById(userId);
        if(user != null){
            userConnectionInfo.put(userId,this); //入表
        }else{
            this.session.close();//关闭会话
        }

    }

    @OnClose
    public void onClose() {
        // 关闭链接 删除表中的映射
        System.out.println("Disconnected!");
        if(this.user != null){
            userConnectionInfo.remove(this.user.getId());
            //匹配池移除用户
            matchpool.remove(this.user);
        }
    }

    //当做路由分配任务
    @OnMessage
    public void onMessage(String message, Session session) {
        // 从Client接收消息
        System.out.println("Receive message!");
        JSONObject data = JSONObject.parseObject(message);//将字符串解析成Json
        String event = data.getString("event");
        if("start-matching".equals(event)){ //防止event为空的异常
            startMatching(data.getInteger("bot_id"));
        }else if ("stop-matching".equals(event)){
            stopMatching();
        }else if ("move".equals(event)) {
            Integer direction = data.getInteger("direction");
            System.out.println(direction);
            move(direction);
        }

    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendMessage(String message){
        // Server发送消息
        synchronized (this.session){
            try {
                this.session.getBasicRemote().sendText(message); //向客户端发送信息
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}